﻿using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;
using SilverSynth.Library;
using System;

namespace SilverSynth.DemoUI
{
    public partial class MainPage : UserControl
    {
        bool playing;
        Mixer mixer;
        ObservableCollection<Preset> presets;
        bool changedOnce;

        public MainPage()
        {
            InitializeComponent();
            this.presets = this.GetPresets();
            this.presetCombo.ItemsSource = presets;
            this.presetCombo.SelectedIndex = 0;
            this.presetCombo.SelectionChanged += new SelectionChangedEventHandler(presetCombo_SelectionChanged);
            this.Loaded += new RoutedEventHandler(MainPage_Loaded);
        }

        void presetCombo_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (!changedOnce)
            {
                changedOnce = true;
                presets.RemoveAt(0);
                presets.Insert(0, new Preset() { Name = "None" });
            }
            this.LoadPreset((Preset)presetCombo.SelectedItem);

        }

        void LoadPreset(Preset preset)
        {
            this.Clear();
            foreach (Channel channel in preset.Channels)
            {
                OscillatorControl newControl = this.AddOscillator(true);
                newControl.Frequency = channel.Frequency;
                newControl.Pan = channel.Pan;
                newControl.FrequencyModulationAmplitude = channel.FrequencyModulationAmplitude;
                newControl.FrequencyModulationFrequency = channel.FrequencyModulationFrequency;
                newControl.AmplitudeModulationFrequency = channel.AmplitudeModulationFrequency;
                newControl.Attenuation = channel.Attenuation;
                newControl.WaveForm = channel.WaveForm;
                //newControl.LoadOscillator(this.mixer);
            }
        }

        void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            this.mixer = new Mixer();
            StereoPcmStreamSource source = new StereoPcmStreamSource();
            source.Input = mixer;
            this.media.SetSource(source);
        }

        void AddOscillatorClick(object sender, RoutedEventArgs e)
        {
            this.AddOscillator();
        }

        OscillatorControl AddOscillator()
        {
            return this.AddOscillator(true);
        }

        OscillatorControl AddOscillator(bool callLoad)
        {
            OscillatorControl newControl = new OscillatorControl();
            newControl.RemoveClicked += new System.EventHandler(newControl_RemoveClicked);
            this.oscillatorContainer.Children.Add(newControl);
            newControl.Title = "Oscillator " + this.mixer.Inputs.Count.ToString();

            if (callLoad)
                newControl.LoadOscillator(this.mixer);
            return newControl;
        }

        void newControl_RemoveClicked(object sender, System.EventArgs e)
        {
            OscillatorControl control = sender as OscillatorControl;
            this.mixer.Remove(control.Output);
            this.oscillatorContainer.Children.Remove(control);
        }

        void ClearClick(object sender, RoutedEventArgs e)
        {
            this.Clear();
        }

        void Clear()
        {
            this.mixer.RemoveAll();
            this.oscillatorContainer.Children.Clear();
        }

        void PlayClick(object sender, RoutedEventArgs e)
        {
            Button button = (Button)sender;
            if (this.playing)
            {
                this.playing = false;
                button.Content = "Play";
                this.media.Stop();
            }
            else
            {
                this.playing = true;
                button.Content = "Stop";
                this.media.Play();
            }
        }

        ObservableCollection<Preset> GetPresets()
        {
            Preset preset = null;
            ObservableCollection<Preset> items = new ObservableCollection<Preset>();

            //default
            preset = new Preset() { Name = "Select a preset..." };
            items.Add(preset);

            //wobble
            preset = new Preset();
            preset.Name = "Wobble";
            preset.Channels.Add(
                new Channel()
                {
                    WaveForm = "Sine",
                    Frequency = 500d,
                    Attenuation = -5d,
                    FrequencyModulationFrequency = 3d,
                    FrequencyModulationAmplitude = 600
                });
            items.Add(preset);

            //fade
            preset = new Preset();
            preset.Name = "Fade";
            preset.Channels.Add(
                new Channel()
                {
                    WaveForm = "Sine",
                    Frequency = 499d,
                    Attenuation = -4d,
                    AmplitudeModulationFrequency = 2d
                });
            items.Add(preset);

            //low drone
            preset = new Preset();
            preset.Name = "Low Drone";
            preset.Channels.Add(
                new Channel()
                {
                    WaveForm = "Sine",
                    Frequency = 100d,
                    Pan = short.MinValue,
                    Attenuation = -10d,
                    FrequencyModulationFrequency = 25d,
                    FrequencyModulationAmplitude = 111
                });
            preset.Channels.Add(
                new Channel()
                {
                    WaveForm = "Sine",
                    Frequency = 101d,
                    Pan = short.MaxValue,
                    Attenuation = -10d,
                    FrequencyModulationFrequency = 26d,
                    FrequencyModulationAmplitude = 116
                });
            preset.Channels.Add(
                new Channel()
                {
                    Frequency = 100d,
                    Attenuation = -38d,
                    AmplitudeModulationFrequency = 37d,
                    WaveForm = "Saw"
                });
            preset.Channels.Add(
                new Channel()
                {
                    WaveForm = "Sine",
                    Frequency = 800d,
                    Pan = short.MinValue,
                    Attenuation = -37d,
                    FrequencyModulationFrequency = 60d,
                    FrequencyModulationAmplitude = 322
                });
            preset.Channels.Add(
                new Channel()
                {
                    WaveForm = "Sine",
                    Frequency = 802d,
                    Pan = short.MaxValue,
                    Attenuation = -35d,
                    FrequencyModulationFrequency = 61d,
                    FrequencyModulationAmplitude = 328
                });

            items.Add(preset);


            //annoying
            preset = new Preset();
            preset.Name = "Annoying";
            preset.Channels.Add(
                new Channel()
                {
                    Frequency = 440d,
                    Pan = short.MinValue,
                    Attenuation = -10d,
                    FrequencyModulationFrequency = 29d,
                    FrequencyModulationAmplitude = 248,
                    AmplitudeModulationFrequency = 24,
                    WaveForm = "Square"
                });
            preset.Channels.Add(
                new Channel()
                {
                    Frequency = 441d,
                    Pan = short.MaxValue,
                    Attenuation = -10d,
                    FrequencyModulationFrequency = 30d,
                    FrequencyModulationAmplitude = 291,
                    AmplitudeModulationFrequency = 26,
                    WaveForm = "Square"
                });
            preset.Channels.Add(
                new Channel()
                {
                    Frequency = 110,
                    Attenuation = -11d,
                    FrequencyModulationFrequency = 18d,
                    FrequencyModulationAmplitude = 243,
                    WaveForm = "Sine"
                });
            preset.Channels.Add(
                new Channel()
                {
                    Frequency = 55,
                    Pan = short.MinValue,
                    Attenuation = -14d,
                    FrequencyModulationFrequency = 29d,
                    FrequencyModulationAmplitude = 148,
                    AmplitudeModulationFrequency = .2,
                    WaveForm = "Saw"
                });
            preset.Channels.Add(
                new Channel()
                {
                    Frequency = 54,
                    Pan = short.MaxValue,
                    Attenuation = -15d,
                    FrequencyModulationFrequency = 28d,
                    FrequencyModulationAmplitude = 153,
                    AmplitudeModulationFrequency = .2,
                    WaveForm = "Saw"
                });

            items.Add(preset);

            return items;
        }
    }
}
